﻿#region Header
// ------------------------ Licence / Copyright ------------------------
// 
// ScrumTable for Scrum Meeting Support
// Copyright © HSR - Hochschule für Technik Rapperswil
// All Rights Reserved
// 
// Author:
//  Michael Gfeller Silvan Gehrig Patrick Boos
// 
// ---------------------------------------------------------------------
#endregion

#region Usings

using System;
using System.Collections.Generic;

#endregion

namespace ScrumTable.Common.Collections
{
    /// <summary>
    /// Contains the global utilities for the IList class.
    /// </summary>
    public static class ListUtil
    {
        #region Methods
        //--------------------------------------------------------------------
        // Methods
        //--------------------------------------------------------------------

        /// <summary>
        /// Loops throught all elements of the current list instance in a
        /// reverse manner.
        /// </summary>
        /// <param name="thisPtr">Specifies the reference to release.</param>
        /// <param name="toExecute">Specfies the action to execute.</param>
        public static void ForEachReverse<T>(this IList<T> thisPtr, Action<T> toExecute)
        {
            PreCondition.AssertNotNull(thisPtr, "thisPtr");
            PreCondition.AssertNotNull(toExecute, "toExecute");

            for (int i = thisPtr.Count - 1; i > -1; --i)
            {
                toExecute(thisPtr[i]);
            }
        }

        /// <summary>
        /// Removes an element using the given comperator from the current
        /// collection.
        /// </summary>
        /// <param name="thisPtr">Specifies the collection instance.</param>
        /// <param name="comparator">Specifies the comparator which is used to evaluate the element to remove.</param>
        public static bool RemoveIf<T>(this IList<T> thisPtr, Predicate<T> comparator)
        {
            PreCondition.AssertNotNull(thisPtr, "thisPtr");
            PreCondition.AssertNotNull(comparator, "comparator");

            T foundElement = default(T);
            int index = 0;

            foreach (T element in thisPtr)
            {
                if (comparator(element))
                {
                    foundElement = element;
                    break;
                }
                ++index;
            }
            if (!Equals(foundElement, default(T)))
            {
                thisPtr.RemoveAt(index);
                return true;
            }
            return false;
        }

        /// <summary>
        /// Removes all elements behind the given range.
        /// </summary>
        /// <param name="thisPtr">Specifies the collection instance.</param>
        /// <param name="rangeStart">Specifies the pointer at which the remove begins.</param>
        public static void RemoveRange<T>(this IList<T> thisPtr, int rangeStart)
        {
            RemoveRange(thisPtr, rangeStart, null);
        }

        /// <summary>
        /// Removes all elements behind the given range.
        /// </summary>
        /// <param name="thisPtr">Specifies the collection instance.</param>
        /// <param name="rangeStart">Specifies the pointer at which the remove begins.</param>
        /// <param name="removeEvent">Specifies a function pointer which will be called if an element has been removed.</param>
        public static void RemoveRange<T>(this IList<T> thisPtr, int rangeStart, Action<T> removeEvent)
        {
            PreCondition.AssertNotNull(thisPtr, "thisPtr");
            PreCondition.AssertNotNull(rangeStart, "rangeStart");

            for (int i = thisPtr.Count - 1; i >= rangeStart; --i)
            {
                T element = thisPtr[i];
                thisPtr.RemoveAt(i);

                if (removeEvent != null)
                {
                    removeEvent(element);
                }
            }
        }

        /// <summary>
        /// Creates a new List instance and adds the elements from the this ptr
        /// instance into the newly created list.
        /// </summary>
        /// <param name="thisPtr">Specifies the list instance to copy the elements (pointers) from.</param>
        public static IList<T> CopyToList<T>(this IList<T> thisPtr)
        {
            PreCondition.AssertNotNull(thisPtr, "thisPtr");

            return thisPtr.Convert(ptr => ptr);
        }

        #endregion
    }
}
